#!/bin/sh

__SPINNER="\\"

# ===========================================================================
# Print an error and exit
# ===========================================================================
fail() {
  echo "$*" >&2
  exit 1
}

putok() {
  if [ -z "$__ECHONE" ]; then
	echotest=`echo -ne`
	if [ -z "$echotest" ]; then
	  __ECHONE="echo -ne"
	  __NHL=""
	else
	  __ECHONE="echo"
	  __NHL="\c"
	fi
  fi
  $__ECHONE "\r*\r$__NHL"
}

# ===========================================================================
# Write a string to stdout with no newline
# ===========================================================================
puts() {
  if [ -z "$COLUMNS" ]; then
    COLUMNS=80
  fi
  
  LN="$*"
  
  first=`echo "$LN" | cut -c1`
  if [ "$first" = ">" ]; then
    case "$__SPINNER" in
      "|")
      	__SPINNER="/"
      	;;
      "/")
      	__SPINNER="-"
      	;;
      "-")
      	__SPINNER="\\"
      	;;
      "\\")
      	__SPINNER="|"
      	;;
     esac
    NLN=`echo "$LN" | cut -c 2-`
    LN="$__SPINNER$NLN"
  fi
  
  __WIDTH=$(expr $COLUMNS '-' 1)
  if [ -z "$__ECHON" ]; then
	echotest=`echo -ne`
	if [ -z "$echotest" ]; then
	  __ECHON="echo -ne"
	  __NHL=""
	else
	  __ECHON="echo"
	  __NHL="\c"
	fi
  fi
  __LINE=`echo "$LN                                                                                   " | cut -c 1-$__WIDTH`
  $__ECHON "$__LINE\r$__NHL"
}

# ===========================================================================
# Derive system's architecture signature
# ===========================================================================
getarch() {
  UN_OS=`uname -o 2>/dev/null || uname`
  UN_PROC=`( uname -i 2>/dev/null || uname -p 2>/dev/null || uname -m ) | cut -f1 -d,`
  
  if [ "$UN_OS" = "GNU/Linux" ]; then
	UN_OS="Linux"
  fi
  
  if [ "$UN_PROC" = "unknown" ]; then
	if [ "$UN_OS" = "Cygwin" ]; then
	  UN_PROC=i386
	elif [ "$UN_OS" = "Linux" ]; then
	  UN_PROC=`uname -m`
	fi
  fi
  UN_PROC=`echo "$UN_PROC" | sed -e "s/^i.86/i386/;s/amd64/x86_64/"`
  echo "$UN_OS.$UN_PROC"
}

# ===========================================================================
# Get default from mkproject output
# ===========================================================================
getprojectdefaults() {
  if [ -f .appname ]; then
    appname=$(cat .appname)
  fi
  if [ -f .appid ]; then
    appid=$(cat .appid)
  fi
}

# ===========================================================================
# Verify a string for a given suffix
# ===========================================================================
endswith() {
  what="$1"
  with="$2"
  orly=`echo "$1" | sed -e "s/.*${with}$/YES/"`
  if [ "$orly" = "YES" ]; then
    return 0
  fi
  return 1
}

# ===========================================================================
# Create a .app bundle directory
# ===========================================================================
mkappdir() {
  puts "> Creating ${1}..."
  dstnam=$(echo "$1" | sed -e "s/\.app$//")
  if [ -d "$1" ]; then
    rm -rf "$1"
  fi
  rm -f "$dstnam"
  mkdir -p "$1"
  putok
  echo ""
}

# ===========================================================================
# Install an executable into a .app bundle
# ===========================================================================
installexe() {
  puts "> Installing executable..."
  fn="$1"
  dst="$2"
  ar="$3"
  dstnam=$(echo "$dst" | sed -e "s/\.app$//")
  apdnam=$(echo "$dst" | sed -e "s/.*\///")
  
  mkdir -p "${dst}/Contents/${ar}"
  cp "$fn" "${dst}/Contents/${ar}/${fn}"
  chmod 755 "${dst}/Contents/${ar}/${fn}"
  ln -s "Contents/${ar}/${fn}" "${dst}/exec"
  ln -s "${apdnam}/exec" "$dstnam"
  putok
  echo ""
}

# ===========================================================================
# Install a resource file into a .app bundle
# ===========================================================================
installrsrc() {
  fn="$1"
  dst="$2"
  typ="$3"
  nam=$(echo "$1" | sed -e "s/.*\///")
  
  mkdir -p "${dst}/Contents/${typ}"
  cp "$fn" "${dst}/Contents/${typ}/${nam}"
  chmod 644 "${dst}/Contents/${typ}/${nam}"
}

showhelp() {
  cat << _EOF_
Usage: grace mkapp [options] <application name>
Options:
    --appid <application-id>    Example: net.example.tools.helloworld
    --arch <arch>               Example: Linux.i386
    --dest <path>               Where to install the application
_EOF_
}

# ===========================================================================
# MAIN
# ===========================================================================
getprojectdefaults

# ---------------------------------------------------------------------------
# Get command line arguments
# ---------------------------------------------------------------------------
while [ ! -z "$1" ]; do
  case "$1" in
  	"--appid")
  		shift
  		appid="$1"
  		shift
  		;;
  	"--arch")
  		shift
  		arch="$1"
  		shift
  		;;
  	"--appname")
  		shift
  		appname="$1"
  		shift
  		;;
  	"--dest")
  		shift
  		destdir=$(echo "$1" | sed -e "s/\/$//")
  		shift
  		;;
  	"--help")
  		showhelp $0
  		exit 0
  		;;
  	"-h")
  		showhelp $0
  		exit 0
  		;;
  	*)
  		appname="$1"
  		shift
  		;;
 esac
done

if [ -z "$destdir" ]; then
  destdir="."
fi

if [ -z "$appname" ]; then
  fail No appname provided and no .appname file found.
fi

if [ -z "$arch" ]; then
  arch=$(getarch)
fi

if [ -z "$appid" ]; then
  appid="local.$appname"
fi

# ---------------------------------------------------------------------------
# Start building the bundle
# ---------------------------------------------------------------------------
echo "* Building ${appname} for ${arch}:"

execfile="${appname}.exe"
appdir="${destdir}/${appname}.app"
mkappdir "$appdir"
datestamp=$(date +%Y-%m-%dT%H:%M:%S)
cat > "${appdir}/.meta" << _EOF_
<?xml version="1.0" encoding="UTF-8"?>
<bundle>
	<grace.appid>${appid}</grace.appid>
	<grace.arch>${arch}</grace.arch>
	<grace.appname>${appname}</grace.appname>
</bundle>
_EOF_
installexe "$execfile" "$appdir" "$arch"

# ---------------------------------------------------------------------------
# Install resource files
# ---------------------------------------------------------------------------
if [ -d rsrc ]; then
  find rsrc -type f -print | while read rsrc; do
	puts "> Installing ${rsrc}..."
	if endswith "$rsrc" ".xml"; then
	  subtype=$(echo "$rsrc" | sed -e "s/.xml$//;s/.*\.//")
	  case "$subtype" in
		"schema")
			installrsrc "$rsrc" "$appdir" "Schemas"
			;;
		"validator")
			installrsrc "$rsrc" "$appdir" "Schemas"
			;;
		"conf")
			installrsrc "$rsrc" "$appdir" "Configuration Defaults"
			;;
		*)
			installrsrc "$rsrc" "$appdir" "Resources"
			;;
	  esac
	else
	  if endswith "$rsrc" ".thtml"; then
		installrsrc "$rsrc" "$appdir" "Templates"
	  else
		installrsrc "$rsrc" "$appdir" "Resources"
	  fi
	fi
	putok
  done
fi

# ---------------------------------------------------------------------------
# Install tools
# ---------------------------------------------------------------------------
if [ -d tools ]; then
  for tool in tools/*; do
    installrsrc "$tool" "$appdir" "Tools"
  done
fi

puts "* Done"
echo ""
